package com.ruoyi.system.condig;
import com.ruoyi.common.log.annotation.Log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @Log 注解的 AOP 切面，负责开启/关闭方法-SQL 关联上下文
 */
@Aspect
@Component
public class LogMethodAspect {

    /**
     * 拦截被 @Log 标记的方法，管理方法上下文
     */
    @Around("@annotation(log)")
    public Object aroundLogMethod(ProceedingJoinPoint joinPoint, Log log) throws Throwable {
        // 1. 生成当前方法的唯一标识（类名+方法名）
        String className = joinPoint.getTarget().getClass().getSimpleName();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodId = className + "." + method.getName();
        String logDesc = log.title();
        //String logDesc = log.value();

        // 2. 开启方法上下文（存入 ThreadLocal）
        MethodSqlContext.startMethod(new MethodSqlContext.MethodLogInfo(methodId, logDesc));

        // 3. 执行目标方法
        Object result;
        try {
            result = joinPoint.proceed();
        } finally {
            // 4. 结束方法上下文，获取该方法执行的所有 SQL
            List<MethodSqlContext.SqlLogInfo> sqls = MethodSqlContext.endMethod();

            // 5. 输出关联日志（方法 + 对应的 SQL）
            printMethodSqlLog(methodId, logDesc, sqls);
        }

        return result;
    }

    /**
     * 打印方法与 SQL 的关联日志
     */
    private void printMethodSqlLog(String methodId, String logDesc, List<MethodSqlContext.SqlLogInfo> sqls) {
        StringBuilder sb = new StringBuilder();
        sb.append("\n===== @Log 方法执行完成：").append(logDesc).append("（").append(methodId).append("）=====\n");
        if (sqls.isEmpty()) {
            sb.append("该方法未执行任何 SQL\n");
        } else {
            sb.append("执行的 SQL 列表：\n");
            for (int i = 0; i < sqls.size(); i++) {
                MethodSqlContext.SqlLogInfo sql = sqls.get(i);
                sb.append(i + 1).append(". ")
                  .append("[类型：").append(sql.getOperationType()).append("，耗时：").append(sql.getExecuteTimeMs()).append("ms] ")
                  .append(sql.getSql()).append("\n");
            }
        }
        sb.append("========================================\n");
        System.out.println(sb.toString());
    }
}

